package com.test.json;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.DateFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;

/**
 * JsonObject. <br>
 * Json对象转换.
 * <p>
 * Copyright: Copyright (c) 2010-4-17 下午04:10:11
 * <p>
 * Company: 北京宽连十方数字技术有限公司
 * <p>
 * Author: liuxl@c-platform.com
 * <p>
 * Version: 1.0
 * <p>
 */
public class JsonObject {

	/** 属性集合 */
	private static Map<String, Map<String, Class<? extends Object>>> propertyMap = new HashMap<String, Map<String, Class<? extends Object>>>();

	/**
	 * 将一个 Object对像转换成Json字符串。 <br>
	 * 
	 * @param object
	 *            对像
	 * @return Json字符串
	 */
	public static String fromObject(Object object) {
		return JsonObject.fromObject(object, null, null, JsonUtil.shortDate);
	}

	/**
	 * 将一个 Object对像指定属性转换成Json字符串。 <br>
	 * 
	 * @param object
	 *            对像
	 * @param item
	 *            属性集合
	 * @return Json字符串
	 */
	public static String fromObject(Object object, String[] item) {
		return JsonObject.fromObject(object, item, null, JsonUtil.shortDate);
	}

	/**
	 * 将一个 Object对像指定属性，指定日期格式 转换成Json字符串。 <br>
	 * 
	 * @param object
	 *            对像
	 * @param item
	 *            属性集合
	 * @param datePattern
	 *            日期格式
	 * @return Json字符串
	 */
	public static String fromObject(Object object, String[] item, int datePattern) {
		return JsonObject.fromObject(object, item, null, datePattern);
	}

	/**
	 * 将一个 Object对像指定属性，指定日期格式 转换成Json字符串。 <br>
	 * 
	 * @param object
	 *            对像
	 * @param item
	 *            属性集合
	 * @param datePattern
	 *            日期格式
	 * @return Json字符串
	 */
	public static String fromObject(Object object, String[] item, String[] item4long2Date) {
		return JsonObject.fromObject(object, item, item4long2Date, JsonUtil.shortDate);
	}

	/**
	 * 使用java对象获取json格式数据
	 * 
	 * @param object
	 *            对象实体
	 * @param item
	 *            获取对象中的属性集合
	 * @param item4long2Date
	 *            需要日期转换的属性
	 * @param datePattern
	 *            日期格式
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static String fromObject(Object object, String[] item, String[] item4long2Date, int datePattern) {
		if (object == null) {
			return "";
		}
		Map<String, Class<? extends Object>> propertyMap = JsonObject.getPropertyMap(object.getClass());

		Map<String, Class<? extends Object>> itemMap = null;

		String jsonString = "";

		DateFormat format = JsonUtil.getDatePattern(datePattern);

		Set<String> item4long2DateSet = new HashSet<String>();

		boolean custom = false;

		if (item != null && item.length > 0) {
			custom = true;
			int size = item.length;
			itemMap = new HashMap<String, Class<? extends Object>>();
			for (int i = 0; i < size; i++) {
				if (propertyMap.containsKey(item[i].split("\\.")[0])) {
					itemMap.put(item[i], propertyMap.get(item[i].split("\\.")[0]));
				}
			}
		} else {
			itemMap = propertyMap;
		}

		if (item4long2Date != null && item4long2Date.length > 0) {
			Collections.addAll(item4long2DateSet, item4long2Date);
		}

		Set<Entry<String, Class<? extends Object>>> entrySet = itemMap.entrySet();

		Iterator<Entry<String, Class<? extends Object>>> iterator = entrySet.iterator();
		String tempJsonString = null;
		boolean isFirst = true;

		while (iterator.hasNext()) {
			Entry<String, Class<? extends Object>> entry = iterator.next();
			String name = entry.getKey();
			Field field = JsonObject.getField(object, name);
			field.setAccessible(true);
			if (field.getModifiers() == Modifier.STATIC && !custom) {
				continue;
			}
			try {
				if (field.get(object) == null) {
					tempJsonString = JsonObject.getValueString(object, field, false, format);
				} else if (name.split("\\.").length > 1) {

					String[] childItem = name.replace(name.split("\\.")[0] + ".", "").split("\\.");
					if (field.get(object) instanceof Collection) {
						tempJsonString = JsonArray.fromList((List) field.get(object), childItem, item4long2Date, datePattern);
					} else {
						if (childItem.length > 1) {
							tempJsonString = "{" + JsonObject.fromObject(field.get(object), childItem, item4long2Date, datePattern) + "}";
						} else {
							tempJsonString = JsonObject.fromObject(field.get(object), childItem, item4long2Date, datePattern);
						}
					}

				} else {
					if (field.get(object) instanceof Collection) {
						tempJsonString = field.getName() + ":null";
						// JsonArray.fromList((List) field.get(object), null,
						// datePattern);
					} else

					if (field.get(object) instanceof String) {
						tempJsonString = JsonObject.getValueString(object, field, false, format);
					} else if (field.get(object) instanceof Number) {
						if (item4long2DateSet.contains(name)) {
							tempJsonString = JsonObject.getValueString(object, field, true, format);
						} else {
							tempJsonString = JsonObject.getValueString(object, field, false, format);
						}
					} else if (field.get(object) instanceof Date) {
						tempJsonString = JsonObject.getValueString(object, field, true, format);
					} else if (custom) {
						tempJsonString = JsonObject.fromObject(field.get(object), null, item4long2Date, datePattern);
					} else {
						tempJsonString = JsonObject.getValueString(object, field, false, format);
					}
				}
				if (isFirst) {
					jsonString = jsonString + tempJsonString;
					isFirst = false;
				} else {
					jsonString = jsonString + "," + tempJsonString;
				}
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}

		return jsonString;
	}

	private static Field getField(Object object, String name) {
		try {
			return object.getClass().getDeclaredField(name.split("\\.")[0]);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@SuppressWarnings("unused")
	private static Map<String, Class<? extends Object>> getPropertyMap(Class<? extends Object> _class) {
		Map<String, Class<? extends Object>> _propertyMap = JsonObject.propertyMap.get(_class.getName());
		if (_propertyMap == null) {
			_propertyMap = new TreeMap<String, Class<? extends Object>>();
			Field[] fields = _class.getDeclaredFields();
			int fieldSize = fields.length;
			for (int i = 0; i < fieldSize; i++) {
				Field field = fields[i];
				_propertyMap.put(field.getName(), field.getType());
			}
			JsonObject.propertyMap.put(_class.getName(), _propertyMap);
		}
		return _propertyMap;
	}

	/**
	 * 使用反射获取对象值。 <br>
	 * 
	 * @param object
	 *            对像
	 * @param field
	 *            属性对像
	 * @param isFormat
	 *            是否格式化
	 * @param format
	 *            格式
	 * @return 字符串
	 */
	private static String getValueString(Object object, Field field, boolean isFormat, DateFormat format) {

		try {
			Object value = field.get(object);
			if (value != null) {
				if (value instanceof Boolean) {
					return field.getName() + ":" + value;
				} else if (value instanceof java.util.Date) {
					return field.getName() + ":\"" + format.format((Date) value) + "\"";
				} else if (isFormat) {
					Date date = new Date((Long) value);
					return field.getName() + ":\"" + format.format(date) + "\"";
				}
				if (value instanceof String) {
					String response = (String) value;
					return field.getName() + ":\"" + response.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r")
					        + "\"";
				} else {
					return field.getName() + ":\"" + value + "\"";
				}
			} else {
				return field.getName() + ":null";
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}